#include <iostream>
#include <string>
#include <unistd.h>
#include <stdlib.h>
#include <vector>
#include <functional>
#include <sys/wait.h>
#include "Channel.hpp"
#include "Task.hpp"

using work_t = std::function<void()>;

enum
{
    OK,
    UsageError,
    PipeError,
    ForkError
};

class ProcessPool
{
public:
    ProcessPool(int n, work_t w) : processnum(n), work(w)
    {
    }

    int InitProcessPool()
    {
        // 2.创建指定个数的进程
        for (int i = 0; i < processnum; i++)
        {
            // 1.先有管道
            int pipefd[2] = {0};
            int n = pipe(pipefd);
            if (n < 0)
                // 管道创建失败
                return PipeError;
            // 创建进程
            pid_t id = fork();
            if (id < 0)
                // 进程创建失败
                return ForkError;
            if (id == 0) // 子进程
            {
                //关闭历史的所继承下来的写端
                std::cout <<getpid()<< ", close child history fd: ";
                for(auto& c: channels)
                {  
                    std::cout << c.getWfd()<<", ";
                    c.Close();
                }

                ::close(pipefd[1]);              // 子进程关写端
                std::cout << "当前读端: " <<pipefd[0]<<std::endl; 
                ::dup2(pipefd[0], STDIN_FILENO); // 重定向读端到每个子进程的标准输入
                ::close(pipefd[0]);              // 重定向后关闭原读端
                Worker();                        // 执行任务循环
                ::exit(0);                       // 子进程正常退出
            }

            // 父进程
            ::close(pipefd[0]); // 父进程关闭读端
            channels.emplace_back(pipefd[1], id);
        }
        return OK;
    }

    // void DebugPrint()
    // {
    //     for( auto& e: channels)
    //     {
    //         std::cout << (e.Name()) <<std::endl;
    //     }
    // }

    void DispatchTask()
    {
        int who = 0;
        // 2.派发任务
        int num = 5;
        while (num--)
        {
            // a.选择任务
            int task = tm.SelectTask(); // 随机选择
            // b.选择一个子进程
            who %= channels.size();          // 保证在是有效进程个数
            Channel &curr = channels[who++]; // 从0开始选进程

            // 测试
            std::cout << std::endl;
            std::cout << "###################" << std::endl;
            std::cout << "send " << task << " to" << curr.Name() << "任务还剩 " << num << std::endl;
            std::cout << "###################" << std::endl;

            // c.派发任务
            curr.Send(task);
            sleep(2); // 每隔俩秒发送
        }
    }
    void CleanProcessPool()
    {
        // version2
        // 关闭读端
        for (int i = channels.size()-1;i >= 0; i--)
        {
            channels[i].Close();
            pid_t rid = ::waitpid(channels[i].getPid(), nullptr, 0);
            if (rid > 0)
            {
                std::cout << "child " << rid << " wait...sucess" << std::endl;
            }
        }

        // //关闭读端
        // for (auto &c : channels)
        // {
        //     c.Close();
        // }
        // // 回收子进程
        // for (auto &c : channels)
        // {
        //     pid_t rid = ::waitpid(c.getPid(), nullptr, 0);
        //     if (rid > 0)
        //     {
        //         std::cout << "child " << rid << " wait...sucess" << std::endl;
        //     }
        // }
    }

private:
    std::vector<Channel> channels;
    int processnum;
    work_t work;
};
